package cn.iocoder.yudao.module.signature.validatap12status.cermb;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 证书处理工具类
 */
public class CertificateUtils {
    
    private static final Logger logger = LoggerFactory.getLogger(CertificateUtils.class);
    
    /**
     * 加载p12证书
     */
    public static KeyStore loadP12Certificate(String p12FilePath, String password) {
        try {
            KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
            try (FileInputStream fis = new FileInputStream(p12FilePath)) {
                keyStore.load(fis, password.toCharArray());
            }
            logger.info("成功加载p12证书文件: {}", p12FilePath);
            return keyStore;
        } catch (Exception e) {
            logger.error("加载p12证书失败", e);
            return null;
        }
    }
    
    /**
     * 提取证书信息
     */
    public static CertificateInfo extractCertificateInfo(KeyStore keyStore) {
        try {
            CertificateInfo certInfo = new CertificateInfo();
            
            // 获取证书别名
            Enumeration<String> aliases = keyStore.aliases();
            if (!aliases.hasMoreElements()) {
                logger.error("p12文件中没有找到证书");
                return null;
            }
            
            String alias = aliases.nextElement();
            certInfo.setAlias(alias);
            
            // 获取证书
            Certificate cert = keyStore.getCertificate(alias);
            if (cert instanceof X509Certificate) {
                X509Certificate x509Cert = (X509Certificate) cert;
                
                // 提取证书信息
                certInfo.setSubjectDN(x509Cert.getSubjectDN().toString());
                certInfo.setIssuerDN(x509Cert.getIssuerDN().toString());
                certInfo.setSerialNumber(x509Cert.getSerialNumber().toString());
                certInfo.setNotBefore(x509Cert.getNotBefore());
                certInfo.setNotAfter(x509Cert.getNotAfter());
                
                // 提取公钥指纹
                String fingerprint = calculateFingerprint(x509Cert);
                certInfo.setFingerprint(fingerprint);
                
                // 提取证书类型（开发/分发）
                String certType = extractCertificateType(x509Cert);
                certInfo.setCertificateType(certType);
                
                logger.info("提取证书信息成功: {}", certInfo);
                return certInfo;
            }
            
        } catch (Exception e) {
            logger.error("提取证书信息失败", e);
        }
        return null;
    }
    
    /**
     * 计算证书指纹
     */
    public static String calculateFingerprint(X509Certificate cert) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        byte[] der = cert.getEncoded();
        md.update(der);
        byte[] digest = md.digest();
        
        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }
    
    /**
     * 提取证书类型
     */
    public static String extractCertificateType(X509Certificate cert) {
        String subject = cert.getSubjectDN().toString();
        if (subject.contains("iPhone Developer")) {
            return "Development";
        } else if (subject.contains("iPhone Distribution") || subject.contains("Apple Distribution")) {
            return "Distribution";
        }
        return "Unknown";
    }
    
    /**
     * 从证书主题中提取Team ID
     */
    public static String extractTeamIdFromSubject(String subjectDN) {
        Pattern pattern = Pattern.compile("OU=([A-Z0-9]{10})");
        Matcher matcher = pattern.matcher(subjectDN);
        if (matcher.find()) {
            return matcher.group(1);
        }
        return null;
    }
    
    /**
     * 验证证书有效期
     */
    public static boolean isCertificateValid(CertificateInfo certInfo) {
        long currentTime = System.currentTimeMillis();
        return certInfo.getNotBefore().getTime() <= currentTime && 
               certInfo.getNotAfter().getTime() >= currentTime;
    }
} 